package org.example;

import org.apache.log4j.Logger;
import org.example.Entity.MyFile;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static org.example.Constant.*;

public class Poll {
    public static Logger log = Server.log;
    //保存key-file
    public static ConcurrentHashMap<String, MyFile> pipeline;
    //保存sequenceId-key的临时结构
    public static ConcurrentHashMap<Integer, String> sequenceId2Key = new ConcurrentHashMap<>();

    public static void init() {
        if (!rootDirectory.exists()) {
            if (!rootDirectory.mkdir()) {
                log.error("主目录创建失败");
                return;
            }
        }
        if (!fileDirectory.exists()) {
            if (!fileDirectory.mkdir()) {
                log.error("创建失败");
                return;
            }
        }
        if (serPath.exists()) {
            try {
                log.info("读取到map.txt文件");
                pipeline = (ConcurrentHashMap<String, MyFile>) deserialize(serPath);
                if (pipeline == null) {
                    pipeline = new ConcurrentHashMap<>();
                }
                if (pipeline.isEmpty()) {
                    log.info("map为空");
                }

            } catch (IOException | ClassNotFoundException e) {
                log.error("读取出现异常");
                log.error(e.getMessage());
                if (serPath.delete()) {
                    log.info("map.ser已删除");
                    pipeline = new ConcurrentHashMap<>();
                } else {
                    log.info("删除失败");
                }
            }
        } else {
            pipeline = new ConcurrentHashMap<>();
            log.info("pipeline已重置");
        }
        deleteUselessFile();
    }

    private static void deleteUselessFile() {
        log.info("删除无用文件");
        Set<String> delKey = new HashSet<>();
        pipeline.forEach((k, file) -> {
            File dir = new File(fileDirectory.toString() + File.separatorChar + k);
            if (!dir.exists() || Objects.requireNonNull(dir.listFiles()).length == 0) {
                delKey.add(k);
            }
        });
        delKey.forEach(k -> {
            pipeline.remove(k);
            Path path = Paths.get(fileDirectory.toString() + File.separatorChar + k);
            if (Files.exists(path)) {
                deleteDir(Paths.get(k));
            }

        });
        if (fileDirectory.list() != null) {
            List<File> files = Arrays.asList(fileDirectory.listFiles());
            files.forEach(file -> {
                if (pipeline.get(file.getName()) == null) {
                    deleteDir(Paths.get(file.getAbsolutePath()));
                }
            });
        }
        save();
    }

    public static synchronized void save() {
        try {
            serialize(serPath.toString(), pipeline);
            log.info("pipeline序列化成功");
        } catch (IOException e) {
            e.printStackTrace();
            log.error("pipeline序列化失败");
            log.error(e.getMessage());
        }
    }
    private static void deleteDir(Path path){
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
                    Files.delete(file); // 有效，因为它始终是一个文件
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir); //这将起作用，因为目录中的文件已被删除
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 序列化对象到指定路径文件
     *
     * @param outPath 文件路径
     * @param outObj  需要序列化的对象
     * @throws IOException 当I/O发生异常时
     */
    public static void serialize(String outPath, Object outObj) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outPath))) {
            oos.writeObject(outObj);
        } catch (Exception e) {
            System.out.println("保存失败");
            e.printStackTrace();
        }
    }

    /**
     * 从文件中逆序列化出对象
     *
     * @param inPath 文件路径
     * @return 你序列化出的对象
     * @throws IOException            当I/O发生异常时
     * @throws ClassNotFoundException 当文件中不存在序列化的对象时
     */
    public static Object deserialize(File inPath) throws IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(inPath))) {
            return ois.readObject();
        }
    }
}
